import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { ROLE_KEY } from './decorator'

// RBAC权限的实现
@Injectable()
// CanActivate：这是 NestJS 中的一个接口，所有的守卫都需要实现这个接口。
// CanActivate 接口定义了一个 canActivate 方法，用于决定请求是否可以继续执行。
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  // ExecutionContext：表示当前执行上下文的对象，它包含了请求的相关信息，如请求对象、响应对象等。
  canActivate(context: ExecutionContext): boolean {
    // 拿到装饰器中的权限
    // Reflector：NestJS 提供的反射器，用于获取元数据。
    // 使用反射器的 getAllAndMerge 方法获取元数据。
    // context.getHandler() 表示当前处理请求的方法，context.getClass() 表示当前处理请求的控制器类。
    // getAllAndMerge 方法会尝试从方法和类上获取指定键的元数据，并将它们合并成一个数组。
    const requiredRoles = this.reflector.getAllAndMerge<string[]>(ROLE_KEY, [context.getHandler(), context.getClass()])

    // 如果 requiredRoles 数组的长度为 0，说明没有在方法或类上设置角色元数据，
    // 即没有对该请求进行角色限制，因此允许请求继续执行，返回 true。
    if (requiredRoles.length === 0) {
      return true
    }

    console.log(`================`)
    console.log(requiredRoles)
    console.log(`================`)

    // 从执行上下文中获取当前的 HTTP 请求对象。
    const { session } = context.switchToHttp().getRequest()
    // 获取用户的role
    const user_role = session.role

    // 判断用户的权限是否在装饰器的权限中   如果有则放行
    if (requiredRoles.includes(user_role)) {
      return true
    } else {
      return false
    }
  }
}
